package com.example.simple;

/**
 * 简单的应用程序入口
 * 演示IoC和AOP的概念
 */
public class SimpleApplication {
    
    public static void main(String[] args) {
        System.out.println("=== Spring IoC和AOP概念演示程序 ===");
        System.out.println();
        
        // 演示IoC：通过容器获取对象，而不是直接new
        System.out.println("1. IoC（控制反转）演示：");
        System.out.println("   传统方式：CalculatorService calculator = new CalculatorService();");
        System.out.println("   IoC方式：通过容器获取对象");
        System.out.println();
        
        // 注册Bean到IoC容器
        SimpleIoCContainer.registerBean("calculator", SimpleCalculatorService.class);
        
        // 从容器获取Bean（依赖注入）
        SimpleCalculatorService calculator = SimpleIoCContainer.getBean(SimpleCalculatorService.class);
        
        System.out.println("2. AOP（面向切面编程）演示：");
        System.out.println("   横切关注点：缓存、日志、异常处理");
        System.out.println();
        
        // 演示各种运算
        demonstrateOperations(calculator);
        
        System.out.println("=== 演示程序结束 ===");
    }
    
    private static void demonstrateOperations(SimpleCalculatorService calculator) {
        System.out.println("--- 演示加法运算（带缓存） ---");
        double result1 = calculator.add(10, 5);
        System.out.println("10 + 5 = " + result1);
        
        // 再次调用相同参数，应该从缓存获取
        double result2 = calculator.add(10, 5);
        System.out.println("10 + 5 = " + result2 + " (应该从缓存获取)");
        System.out.println();
        
        System.out.println("--- 演示减法运算（带缓存） ---");
        double result3 = calculator.subtract(10, 3);
        System.out.println("10 - 3 = " + result3);
        
        // 再次调用相同参数，应该从缓存获取
        double result4 = calculator.subtract(10, 3);
        System.out.println("10 - 3 = " + result4 + " (应该从缓存获取)");
        System.out.println();
        
        System.out.println("--- 演示乘法运算（无缓存，只有日志） ---");
        double result5 = calculator.multiply(6, 7);
        System.out.println("6 * 7 = " + result5);
        
        // 再次调用，没有缓存，会重新计算
        double result6 = calculator.multiply(6, 7);
        System.out.println("6 * 7 = " + result6 + " (重新计算)");
        System.out.println();
        
        System.out.println("--- 演示除法运算（异常处理） ---");
        try {
            double result7 = calculator.divide(10, 2);
            System.out.println("10 / 2 = " + result7);
        } catch (Exception e) {
            System.out.println("除法运算异常: " + e.getMessage());
        }
        
        try {
            double result8 = calculator.divide(10, 0);
            System.out.println("10 / 0 = " + result8);
        } catch (Exception e) {
            System.out.println("除法运算异常: " + e.getMessage());
        }
        System.out.println();
        
        System.out.println("--- 演示幂运算（带缓存） ---");
        double result9 = calculator.power(2, 8);
        System.out.println("2 ^ 8 = " + result9);
        
        // 再次调用相同参数，应该从缓存获取
        double result10 = calculator.power(2, 8);
        System.out.println("2 ^ 8 = " + result10 + " (应该从缓存获取)");
        System.out.println();
        
        System.out.println("--- 演示阶乘运算（带缓存） ---");
        long result11 = calculator.factorial(5);
        System.out.println("5! = " + result11);
        
        // 再次调用相同参数，应该从缓存获取
        long result12 = calculator.factorial(5);
        System.out.println("5! = " + result12 + " (应该从缓存获取)");
        
        try {
            long result13 = calculator.factorial(-1);
            System.out.println("-1! = " + result13);
        } catch (Exception e) {
            System.out.println("阶乘运算异常: " + e.getMessage());
        }
        System.out.println();
        
        System.out.println("--- 演示缓存效果（性能对比） ---");
        
        // 第一次调用，会计算
        System.out.println("第一次调用阶乘 6!");
        long start1 = System.currentTimeMillis();
        long result14 = calculator.factorial(6);
        long end1 = System.currentTimeMillis();
        System.out.println("6! = " + result14 + ", 耗时: " + (end1 - start1) + "ms");
        
        // 第二次调用，从缓存获取
        System.out.println("第二次调用阶乘 6!");
        long start2 = System.currentTimeMillis();
        long result15 = calculator.factorial(6);
        long end2 = System.currentTimeMillis();
        System.out.println("6! = " + result15 + ", 耗时: " + (end2 - start2) + "ms (从缓存获取)");
        
        // 调用不同参数，重新计算
        System.out.println("调用阶乘 7!");
        long start3 = System.currentTimeMillis();
        long result16 = calculator.factorial(7);
        long end3 = System.currentTimeMillis();
        System.out.println("7! = " + result16 + ", 耗时: " + (end3 - start3) + "ms");
        System.out.println();
        
        System.out.println("=== 概念总结 ===");
        System.out.println("1. IoC（控制反转）：");
        System.out.println("   - 对象不再自己创建依赖，而是由容器注入");
        System.out.println("   - 降低了代码耦合度，提高了可维护性");
        System.out.println();
        System.out.println("2. AOP（面向切面编程）：");
        System.out.println("   - 将横切关注点（缓存、日志、异常处理）从业务逻辑中分离");
        System.out.println("   - 避免了代码重复，提高了代码的模块化程度");
        System.out.println();
        System.out.println("3. 缓存切面：");
        System.out.println("   - 自动缓存方法结果，提高性能");
        System.out.println("   - 支持缓存过期时间设置");
        System.out.println();
        System.out.println("4. 日志切面：");
        System.out.println("   - 自动记录方法执行信息");
        System.out.println("   - 记录方法参数、执行时间、异常信息");
    }
}
